package com.xianniu.ltc.service.impl;

import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.Query;
import cn.devezhao.persist4j.engine.ID;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rebuild.core.Application;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.configuration.general.ClassificationManager;
import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.privileges.DepartmentService;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.privileges.bizz.User;
import com.xianniu.ltc.common.Constant;
import com.xianniu.ltc.enums.*;
import com.xianniu.ltc.mapper.*;
import com.xianniu.ltc.model.entity.*;
import com.xianniu.ltc.model.po.*;
import com.xianniu.ltc.model.po.imports.ImportAccountPO;
import com.xianniu.ltc.model.vo.XnAccountVO;
import com.xianniu.ltc.model.vo.XnAccountVO;
import com.xianniu.ltc.service.XnAccountService;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WangRuiJie
 * @Title: AccountServiceImpl
 * @Package com.xianniu.ltc.service.impl
 * @Description:
 * @date 2021/6/172:57 下午
 */
@Slf4j
@Service
public class XnAccountServiceImpl implements XnAccountService {

    @Resource
    private TXnAccountMapper accountMapper;
    @Resource
    private TXnAccountTeamMapper accountTeamMapper;
    @Resource
    private TUserMapper userMapper;
    @Resource
    private TDepartmentMapper departmentMapper;
    @Resource
    private TXnLimitRuleMapper ruleMapper;
    @Resource
    private TXnAccountRecordMapper recordMapper;
    @Resource
    private TSihaikehuMapper sihaikehuMapper;
    @Resource
    private TGonghaikehuMapper gonghaikehuMapper;
    @Resource
    private TMetaFieldMapper metaFieldMapper;


    @Override
    public IPage<XnAccountVO> selectAccountForAdmin(QueryAccountAdminPO po) {
        String tenantCode = UserContextHolder.getTenant();
        Page<TXnAccountDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        IPage<XnAccountVO> dtoList = accountMapper.selectPageList(page, po, Constant.INT_0, tenantCode);
        return dtoList;
    }

    @Override
    public XnAccountVO detailAccount(String id) {
        String entityName = MetadataHelper.getEntityName(ID.valueOf(id));
        XnAccountVO vo = new XnAccountVO();
        // 私海客户
        if (entityName.equalsIgnoreCase("sihaikehu")){
            accountMapper.detailPAccountForAdmin(id);
        }else {
            // 公海客户
            accountMapper.detailCAccountForAdmin(id);
        }
        return vo;
    }

    /**
     * 后台:客户管理转移分组：
     *  校验已领取的不能转移：585为私海客户，私海客户不能转移
     * @param po
     * @return
     */
    @Override
    public ReturnT transferAccountForAdmin(TransferAccountPO po) {
        Boolean flag =false;
        for (String id:po.getAccountIdList()){
            if (id.contains(EntityHelper.SiHaiKeHu+"")){
                flag = true;
            }
        }
        if (flag){
            return new ReturnT(400, "已领取的客户不能转移");
        }
        int i = 0;
        TXnAccountTeamDTO teamDTO = accountTeamMapper.selectById(po.getAccountTeamId());
        if (Objects.isNull(teamDTO)){
            i = accountMapper.updateBatchForIdList(po.getAccountIdList(), Constant.DEFAULT_TEAM_NAME);
        }else {
            i=  accountMapper.updateBatchForIdList(po.getAccountIdList(), teamDTO.getTeamName());
        }
        return i>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }

    /**
     * 后台客户管理：删除客户
     *  校验:客户是已领取（在私海客户中的）不允许删除
     *  逻辑：
     *      1通过客户ID查询公海客户数据，删除公海客户
     *      2，赋值回收站客户实体，然后新增一条回收站客户数据
     * @param idList
     * @return
     */
    @Override
    public ReturnT deleteAccountForAdmin(List<String> idList) {
        Boolean flag =false;
        for (String id:idList){
            if (id.contains(EntityHelper.SiHaiKeHu+"")){
                flag = true;
            }
        }
        if (flag){
            return new ReturnT(400, "已领取的客户不能删除");
        }
        for (String id : idList){
            TGonghaikehuDTO dto = gonghaikehuMapper.selectById(id);
            // 公海删除客户
            gonghaikehuMapper.deleteById(id);
            //xnAccount做回收站表，回收站新增一条删除的数据
            TXnAccountDTO accountDTO = new TXnAccountDTO();
            BeanUtils.copyProperties(dto, accountDTO);
            accountDTO.setDelYn(Constant.INT_1);
            ID accountId= ID.newId(EntityHelper.XnAccount);
            accountDTO.setAccountId(String.valueOf(accountId));
            accountDTO.setReceiveStatus(dto.getReceiveStatus().equalsIgnoreCase("未领取")?"0":"1");
            if (StringUtils.isNotBlank(dto.getKehuzhuangtai())){
                accountDTO.setKehuzhuangtai(AccountStatusEnum.getByValue(dto.getKehuzhuangtai()).getKey());
            }
            accountDTO.setModifiedOn(new Date());
            accountMapper.insert(accountDTO);
        }
        return new ReturnT(200,"操作成功"+idList.size()+"条");
    }

    @Override
    public IPage<XnAccountVO> selectAccountFallbackForAdmin(QueryAccountAdminPO po) {
        String tenantCode = UserContextHolder.getTenant();
        Page<TXnAccountDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        IPage<XnAccountVO> dtoList = accountMapper.selectFallbackPageList(page, po, Constant.INT_1, tenantCode);
        return dtoList;
    }

    /**
     * 后台客户回收站：还原客户
     *  逻辑：
     *      1，通过客户ID查询回收站客户数据，删除回收站客户
     *      2，赋值公海客户实体，然后新增一条公海客户数据
     * @param idList
     * @return
     */
    @Override
    public ReturnT resetAccountForAdmin(List<String> idList) {
        // 循环id查询客户的客户组ID
        for (String id :idList) {
            TXnAccountDTO dto = accountMapper.selectById(id);
            accountMapper.deleteById(id);
            // 不存在：修改该客户的客户组为全公司客户组，修改客户删除状态为0（未删除）
            QueryWrapper<TXnAccountTeamDTO> wrapper = new QueryWrapper<>();
            wrapper.eq("TEAM_NAME", dto.getTeamId());
            TXnAccountTeamDTO teamDTO = accountTeamMapper.selectOne(wrapper);
            if (Objects.isNull(teamDTO)){
                dto.setTeamId(Constant.DEFAULT_TEAM_NAME);
            }
            // 新增一条公海客户数据
            TGonghaikehuDTO gonghaixiansuoDTO = new TGonghaikehuDTO();
            BeanUtils.copyProperties(dto, gonghaixiansuoDTO);
            ID accountId= ID.newId(EntityHelper.GongHaiKeHu);
            gonghaixiansuoDTO.setGonghaikehuId(String.valueOf(accountId));
            gonghaixiansuoDTO.setReceiveStatus(dto.getReceiveStatus().equalsIgnoreCase("0")?"未领取":"已领取");
            if (StringUtils.isNotBlank(dto.getKehuzhuangtai())){
                gonghaixiansuoDTO.setKehuzhuangtai(AccountStatusEnum.getByKey(dto.getKehuzhuangtai()).getValue());
            }
            gonghaixiansuoDTO.setModifiedOn(new Date());
            gonghaikehuMapper.insert(gonghaixiansuoDTO);
        }
        return ReturnT.SUCCESS;
    }

    @Override
    public IPage<XnAccountVO> selectAccountForHighSea(QueryAccountHighSeaPO po) {
        int rows = (int) po.getPageSize();
        int page = (int) po.getPageNum();
        ID currentUser = UserContextHolder.getUser();
        String tenantCode = UserContextHolder.getTenant();
        TUserDTO userDTO = userMapper.selectById(currentUser.toString());
        // 查询当前登录人对应组织ID及该组织下属组织ID集合
        List<String> deptArray = new ArrayList<>();
        deptArray.add(userDTO.getDeptId());
        getDeptList(deptArray, userDTO.getDeptId());
        List<XnAccountVO> dtoList = new ArrayList<>();
        List<XnAccountVO> dtoList1 =accountMapper.selectHighSeaPageList(po, deptArray, Constant.INT_0, tenantCode);
        List<XnAccountVO> dtoList2 =accountMapper.selectCommonHighSeaPageList(po, deptArray, Constant.INT_0, tenantCode);
        dtoList.addAll(dtoList1);
        dtoList.addAll(dtoList2);
        // 数据去重
        dtoList = dtoList.stream().distinct().collect(Collectors.toList());
        // 对list集合进行分页处理
        int total=dtoList.size();
        dtoList=dtoList.subList(rows*(page-1), ((rows*page)>total?total:(rows*page)));
        IPage<XnAccountVO> pageList = new Page<>();
        pageList.setRecords(dtoList);
        pageList.setTotal(dtoList.size());
        return pageList;
    }

    /**
     * 递归查询：根据组织ID查询下级组织的ID集合，依次循环查询所有第一级下组织的子组织ID列表
     * @param deptAll
     * @param parentId
     */
    public void getDeptList(List<String> deptAll, String parentId){
        List<String> deptList = departmentMapper.selectDeptId(parentId);
        if (!deptList.isEmpty()){
            for (String deptId : deptList){
                deptAll.add(deptId);
                getDeptList(deptAll, deptId);
            }
        }
    }

    /**
     * 公海客户删除
     * 校验：当前操作人是该客户对应客户组的负责人才能删除
     * 逻辑：
     *  1，根据ID删除公海客户
     *  2，赋值回收站客户实体，新增一条回收站客户数据
     * @param id
     * @return
     */
    @Override
    public ReturnT deleteAccountForHighSea(String id) {
        ID currentUser = UserContextHolder.getUser();
        String headBy = accountMapper.selectHeadBy(id);
        if (!headBy.equals(currentUser.toString())) return new ReturnT(400,"不是该客户对应客户组负责人，不能删除");
        TGonghaikehuDTO dto = gonghaikehuMapper.selectById(id);
        // 公海删除客户
        gonghaikehuMapper.deleteById(id);
        // 赋值回收站客户实体，新增一条回收站客户数据
        TXnAccountDTO accountDTO = new TXnAccountDTO();
        BeanUtils.copyProperties(dto, accountDTO);
        accountDTO.setDelYn(Constant.INT_1);
        ID accountId= ID.newId(EntityHelper.XnAccount);
        accountDTO.setAccountId(String.valueOf(accountId));
        accountDTO.setReceiveStatus(dto.getReceiveStatus().equalsIgnoreCase("未领取")?"0":"1");
        if (StringUtils.isNotBlank(dto.getKehuzhuangtai())){
            accountDTO.setKehuzhuangtai(AccountStatusEnum.getByValue(dto.getKehuzhuangtai()).getKey());
        }
        int i = accountMapper.insert(accountDTO);
        return i>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }

    /**
     * 公海客户分派
     * 校验：当前操作人是该客户对应客户组的负责人才能分派
     * 逻辑：
     *  1，根据ID删除公海客户
     *  2，赋值私海客户实体，新增一条私海客户数据
     * @param po
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public ReturnT assignAccountForHighSea(AssignAccountPO po) {
        ID currentUser = UserContextHolder.getUser();
        TGonghaikehuDTO dto = gonghaikehuMapper.selectById(po.getId());
        String headBy = accountMapper.selectHeadBy(po.getId());
        if (!headBy.equals(currentUser.toString())) return new ReturnT(400,"【"+dto.getKehumingcheng()+"】对应客户组负责人不是当前操作人，不能操作指派");
        // 限制数量规则校验领取数量是否已达到上限
        if (checkCountRule(po.getTo())){
            return new ReturnT(400, "领取人已达到客户领取数量上限，不能操作");
        }


        // 公海删除客户
        gonghaikehuMapper.deleteById(po.getId());
        // 赋值私海客户实体，新增一条私海客户数据
        TSihaikehuDTO sihaikehuDTO = new TSihaikehuDTO();
        BeanUtils.copyProperties(dto, sihaikehuDTO);
        sihaikehuDTO.setReceiveStatus("已领取");
        sihaikehuDTO.setOwningUser(po.getTo());
        User u = Application.getUserStore().getUser(ID.valueOf(po.getTo()));
        sihaikehuDTO.setOwningDept(String.valueOf(u.getOwningDept().getIdentity()));
        sihaikehuDTO.setCreatedOn(new Date());
        sihaikehuDTO.setModifiedOn(new Date());
        ID accountId= ID.newId(EntityHelper.SiHaiKeHu);
        sihaikehuDTO.setSihaikehuId(String.valueOf(accountId));
        sihaikehuDTO.setIsLock(Constant.F);
        int i = sihaikehuMapper.insert(sihaikehuDTO);
        return i>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }

    /**
     * 公海客户领取
     * 校验：领取规则校验
     * 逻辑：
     *  1，根据ID删除公海客户
     *  2，赋值私海客户实体，新增一条私海客户数据
     * @param id
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public ReturnT receiveAccountForHighSea(String id) {
        ID currentUser = UserContextHolder.getUser();
        TGonghaikehuDTO dto = gonghaikehuMapper.selectById(id);
        // 领取次数规则校验领取次数是否已达到上限
        if (checkReceiveRule(currentUser.toString())){
            return new ReturnT(400, "领取人已达到领取次数上限，不能操作");
        }
        // 限制数量规则校验领取数量是否已达到上限
        if (checkCountRule(currentUser.toString())){
            return new ReturnT(400, "领取人已达到客户领取数量上限，不能操作");
        }
        // 再次领取规则校验
        if (checkAgainReceiveRule(dto.getZidongweiyibianhao(), currentUser.toString())){
            return new ReturnT(400, "未到再次领取时间，不能操作");
        }

        // 公海删除客户
        gonghaikehuMapper.deleteById(id);
        // 赋值私海客户实体，新增一条私海客户数据
        TSihaikehuDTO sihaikehuDTO = new TSihaikehuDTO();
        BeanUtils.copyProperties(dto, sihaikehuDTO);
        sihaikehuDTO.setReceiveStatus("已领取");
        sihaikehuDTO.setOwningUser(currentUser.toString());
        User u = Application.getUserStore().getUser(currentUser);
        sihaikehuDTO.setOwningDept(String.valueOf(u.getOwningDept().getIdentity()));
        sihaikehuDTO.setCreatedOn(new Date());
        sihaikehuDTO.setModifiedOn(new Date());
        ID accountId= ID.newId(EntityHelper.SiHaiKeHu);
        sihaikehuDTO.setSihaikehuId(String.valueOf(accountId));
        sihaikehuDTO.setIsLock(Constant.F);
        int i = sihaikehuMapper.insert(sihaikehuDTO);
        return i>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }

    @Override
    public ReturnT addAccountForHighSea(AddXnAccountPO po) {
        TXnAccountDTO dto = new TXnAccountDTO();
        BeanUtils.copyProperties(po, dto);
        ID userId= ID.newId(EntityHelper.XnAccount);
        dto.setAccountId(String.valueOf(userId));
        dto.setModifiedBy(po.getCreatedBy());
        dto.setOwningUser(po.getCreatedBy());
        dto.setTeamId(Constant.DEFAULT_ACCOUNT_TEAM);
        ID accountId= ID.newId(EntityHelper.XnAccount);
        dto.setAccountId(String.valueOf(accountId));
        int result = accountMapper.insert(dto);
        return result>0? new ReturnT(String.valueOf(userId)):new ReturnT(400, "操作失败");
    }

    @Override
    public IPage<XnAccountVO> selectAccountForPrivateSea(QueryAccountHighSeaPO po) {
        ID currentUser = UserContextHolder.getUser();
        String tenantCode = UserContextHolder.getTenant();
        Page<TXnAccountDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        // 查询登录人是领取人的客户数据集合
        IPage<XnAccountVO> dtoList = accountMapper.selectAccountForPrivateSea(page, po, currentUser.toString(), Constant.INT_0, tenantCode);
        return dtoList;
    }

    @Override
    public ReturnT addAccountForPrivateSea(AddXnAccountPO po) {
        ID currentUser = UserContextHolder.getUser();
        TXnAccountDTO dto = new TXnAccountDTO();
        BeanUtils.copyProperties(po, dto);
        ID userId= ID.newId(EntityHelper.XnAccount);
        dto.setAccountId(String.valueOf(userId));
        dto.setModifiedBy(po.getCreatedBy());
        dto.setTeamId(Constant.DEFAULT_ACCOUNT_TEAM);
        dto.setReceiveStatus(Constant.INT_1.toString());
        dto.setReceiveBy(currentUser.toString());
        dto.setReceiveOn(new Date());
        int result = accountMapper.insert(dto);
        return result>0? new ReturnT(String.valueOf(userId)):new ReturnT(400, "操作失败");
    }

    /**
     * 私海客户：强制收回也是放回公海
     * @return
     */
    @Override
    public ReturnT recycleAccountForPrivateSea(PutAccountPO po) {
        return checkAccountIsReferenced(po, false);
    }

    /**
     * 私海客户：放回公海客户
     * 逻辑：
     *  1，删除私海客户
     *  2，新增公海客户
     * @param po
     * @return
     */
    @Override
    public ReturnT putBackAccountForPrivateSea(PutAccountPO po) {
        return checkAccountIsReferenced(po, true);
    }

    /**
     * 逻辑：
     *  1.查询客户所在所有实体是否被引用
     *  2，被引用&没有分派人则提示被应用，请选择新所属人
     *  3，被引用&有分派人则修改私海客户数据的所属人为分派的指定人员
     *  4，未被引用则则删除私海客户，生成公海客户
     * @param po
     * @return
     */
    public ReturnT checkAccountIsReferenced(PutAccountPO po, Boolean flag){
        String tenantCode = UserContextHolder.getTenant();
        // 校验手动放回或者强制收回的私海客户有没有被引用，有的话则需要指派新所属人
        List<TMetaFieldDTO>  fieldDTOList = metaFieldMapper.selectListByField(null, "sihaikehu", null);
        List<Object> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fieldDTOList)){
            for (TMetaFieldDTO fieldDTO : fieldDTOList ){
                String sql = String.format("select %s from %s where %s = ? and tenantCode = ?",
                        fieldDTO.getFieldName(), fieldDTO.getBelongEntity(), fieldDTO.getFieldName());
                Query query = Application.getQueryFactory().createQueryNoFilter(sql);
                Object[][] array = query
                        .setParameter(1, ID.valueOf(po.getId()))
                        .setParameter(2, tenantCode)
                        .array();
                // 数组转换为集合
                if (array != null){
                    for (int i = 0; i < array.length; i++) {
                        for (int j = 0; j < array[i].length; j++) {
                            list.add(array[i][j]);
                        }
                    }
                }
            }
        }
        // 客户被引用
        if (!CollectionUtils.isEmpty(list)){
            log.info("客户:{}被引用",po.getId());
            if (StringUtils.isBlank(po.getTo())){
                return new ReturnT(400, "数据被其他实体引用，请分派新所属人");
            }else {
                TSihaikehuDTO dto = sihaikehuMapper.selectById(po.getId());
                if (dto != null){
                    dto.setOwningUser(po.getTo());
                    dto.setModifiedOn(new Date());
                    sihaikehuMapper.updateById(dto);
                }
            }
            return new ReturnT(200, "操作成功");
        }else {
            log.info("客户:{}未被引用",po.getId());
            // 未被引用，则删除私海客户，生成公海客户
            return putBackAccountForPrivateSea(po.getId(), flag);
        }
    }

    /**
     * 私海客户：放回公海客户
     * 逻辑：
     *  1，删除私海客户
     *  2，新增公海客户
     * @param id
     * @return
     */
    public ReturnT putBackAccountForPrivateSea(String id, Boolean flag) {
        // 私海删除客户
        TSihaikehuDTO dto = sihaikehuMapper.selectById(id);
         // 强制收回不管是否被锁定
        if (flag){
            if(Constant.T.equals(dto.getIsLock())){
                return new ReturnT(400, "客户已锁定，不能操作");
            }
        }
        sihaikehuMapper.deleteById(id);
        // 赋值私海客户实体，新增一条私海客户数据
        TGonghaikehuDTO tGonghaikehuDTO = new TGonghaikehuDTO();
        BeanUtils.copyProperties(dto, tGonghaikehuDTO);
        tGonghaikehuDTO.setOwningUser(UserService.ADMIN_USER.toString());
        tGonghaikehuDTO.setReceiveStatus("未领取");
        tGonghaikehuDTO.setCreatedOn(new Date());
        tGonghaikehuDTO.setModifiedOn(new Date());
        ID accountId= ID.newId(EntityHelper.GongHaiKeHu);
        tGonghaikehuDTO.setGonghaikehuId(String.valueOf(accountId));
        int result = gonghaikehuMapper.insert(tGonghaikehuDTO);
        return result>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }


    /**
     * 锁定客户，修改客户状态为已锁定
     * @param id
     * @return
     */
    @Override
    public ReturnT lockAccountForPrivateSea(String id) {
        TSihaikehuDTO dto = sihaikehuMapper.selectById(id);
        // 锁定则解锁，否则锁定
        if(Constant.T.equals(dto.getIsLock())){
            dto.setIsLock(Constant.F);
            sihaikehuMapper.updateById(dto);
            return new ReturnT(200,"解除成功");
        }else {
            // 查询限制锁定规则的锁定数量
            if (checkLockRule(dto.getOwningUser())) {
                return new ReturnT(400, "已达到最大锁定记录数，不能操作");
            }
            dto.setIsLock(Constant.T);
            sihaikehuMapper.updateById(dto);
            return new ReturnT(200,"锁定成功");
        }
    }

    /********************************* 规则校验相关 *******************************/

    /**
     * 限制数量规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkCountRule(String receiveBy){
        TXnLimitRuleDTO ruleDTO = selectLimitRule(receiveBy, Constant.COUNT_RULE);
        // 角色没有配置限制规则的，不加数量限制
        if(Objects.isNull(ruleDTO)) return false;
        // 查看领取人已领取的客户数量
        QueryWrapper<TSihaikehuDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("OWNING_USER", receiveBy);
        Integer count = sihaikehuMapper.selectCount(wrapper);
        // 已分派数 == 限制数量 || 已分派数 > 限制数量
        if (count.equals(ruleDTO.getValue()) || count > ruleDTO.getValue()){
            return true;
        }
        return false;
    }

    /**
     * 领取规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkReceiveRule(String receiveBy) {
        TXnLimitRuleDTO ruleDTO = selectLimitRule(null, Constant.RECEIVE_RULE);
        // 角色没有领取规则的，不加领取次数限制
        if(Objects.isNull(ruleDTO)) return false;
        // 查看领取人已领取的客户次数
        QueryWrapper<TXnAccountRecordDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("receive_by", receiveBy);
        if (ruleDTO.getLabel().equals(Constant.WEEK)){
            wrapper.between("receive_on", DateUtil.lastWeek(), new Date());
        }else {
            wrapper.between("receive_on", DateUtil.lastMonth(), new Date());
        }
        Integer count = recordMapper.selectCount(wrapper);
        // 领取的次数 == 规则对应的次数 || 领取的次数 > 规则对应的次数 提示领取次数已达上限
        if (count.equals(ruleDTO.getValue()) || count > ruleDTO.getValue()){
            return true;
        }
        return false;
    }

    /**
     * 再次领取规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkAgainReceiveRule(String code, String receiveBy) {
        TXnLimitRuleDTO ruleDTO = selectLimitRule(null, Constant.AGAIN_RULE);
        // 1，查询领取人对该客户的领取记录
        QueryWrapper<TXnAccountRecordDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("account_id", code);
        wrapper.eq("receive_by", receiveBy);
        TXnAccountRecordDTO dto = recordMapper.selectOne(wrapper);
        // 2.1，客户记录表中存在
        if (Objects.nonNull(dto)){
            // 3，计算时间是否满足再次领取规则
            long hours = DateUtil.between(dto.getReceiveOn(), new Date(), DateUnit.HOUR);
            // 4，客户领取人是当前领取人 && 再次领取时间已满足
            if (Objects.isNull(ruleDTO)){
                dto.setReceiveOn(new Date());
                recordMapper.updateById(dto);
                return false;
            }else {
                if (hours > ruleDTO.getValue() * 24){
                    dto.setReceiveOn(new Date());
                    recordMapper.updateById(dto);
                    return false;
                }
            }
        }else {
            // 2.2，新增领取记录
            TXnAccountRecordDTO dto1 = new TXnAccountRecordDTO();
            dto1.setAccountId(code);
            dto1.setReceiveBy(receiveBy);
            dto1.setReceiveOn(new Date());
            recordMapper.insert(dto1);
            return false;
        }
        return true;
    }

    /**
     * 限制规则查询
     * @param userId
     * @param ruleCode
     * @return
     */
    private TXnLimitRuleDTO selectLimitRule(String userId, String ruleCode){
        QueryWrapper<TXnLimitRuleDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("entity", Constant.ACCOUNT_ENTITY);
        wrapper.eq("rule_code", ruleCode);
        wrapper.eq("is_disable", Constant.INT_0);
        if (userId != null){
            TUserDTO dto = userMapper.selectById(userId);
            wrapper.eq("label", dto.getRoleId());
        }
        TXnLimitRuleDTO ruleDTO = ruleMapper.selectOne(wrapper);
        return ruleDTO;
    }

    /**
     * 限制客户锁规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkLockRule(String receiveBy){
        TXnLimitRuleDTO ruleDTO = selectLimitRule(null, Constant.LOCK_RULE);
        if(ruleDTO == null){
            return true;
        }
        QueryWrapper<TSihaikehuDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("OWNING_USER", receiveBy);
        wrapper.eq("IS_LOCK", Constant.T);
        int i = sihaikehuMapper.selectCount(wrapper);
        if (i == ruleDTO.getValue() || i> ruleDTO.getValue()){
            return true;
        }
        return false;
    }

    /**
     * 保存导入的客户数据
     * @param excelList
     * @param tenantCode
     * @return
     */
    @Override
    public Integer saveImportAccount(List<ImportAccountPO> excelList, String tenantCode) throws Exception{
        int count=0;
        for (ImportAccountPO userExcel : excelList) {
            TGonghaikehuDTO dto = new TGonghaikehuDTO();
            BeanUtils.copyProperties(userExcel, dto);
            ID id= ID.newId(EntityHelper.GongHaiKeHu);
            dto.setGonghaikehuId(String.valueOf(id));
            dto.setCreatedBy(String.valueOf(UserService.ADMIN_USER));
            dto.setModifiedBy(String.valueOf(UserService.ADMIN_USER));
            dto.setOwningUser(String.valueOf(UserService.ADMIN_USER));
            dto.setOwningDept(String.valueOf(DepartmentService.ROOT_DEPT));
            dto.setTenantCode(tenantCode);
            dto.setTeamId("无归属");
            dto.setReceiveStatus("未领取");
            dto.setZidongweiyibianhao(String.valueOf(id));
            Entity test = MetadataHelper.getEntity("gonghaikehu");
            Field classification = test.getField("area");
            ID itemId = ClassificationManager.instance.findItemByName(userExcel.getArea(), classification);
            if (itemId != null){
                dto.setArea(String.valueOf(itemId));
            }else {
                dto.setArea(null);
            }
            int i = gonghaikehuMapper.insert(dto);
            count = count+i;
        }
        return count;
    }

    /**
     * 客户管理：按照条件查询导出的客户数据
     * @param query
     * @return
     */
    @Override
    public List<XnAccountVO> selectExportAccountForAdmin(JSONObject query, Integer dr) {
        String tenantCode = UserContextHolder.getTenant();
        QueryAccountAdminPO po = new QueryAccountAdminPO();
        po.setPageNum(query.getInteger("pageNo"));
        // 1：选中的数据 2：当前页的数据 3：查询后的数据 4：全部数据
        if (dr == 1){
            po.setPageSize(query.getInteger("pageSize"));
            // 根据特殊字符"|"进行分割
            List<String> leadIds = Arrays.asList(query.getString("_selected").split("\\|"));
            po.setAccountIds(leadIds);
        }else if (dr == 2){
            po.setPageSize(query.getInteger("pageSize"));
            boolean filterNonNull = Objects.nonNull(query.getString("param"));
            if(filterNonNull){
                po.setAccountName(query.getString("param"));
            }
        }else if (dr == 3){
            po.setPageSize(Constant.MAX_EXPORT);
            // 校验是否是条件查询
            boolean filterNonNull = Objects.nonNull(query.getString("param"));
            if(filterNonNull){
                po.setAccountName(query.getString("param"));
            }
        }else if (dr == 10){
            po.setPageSize(Constant.MAX_EXPORT);
        }
        Page<TXnAccountDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        List<XnAccountVO> dtoList = accountMapper.selectExportList(page, po, tenantCode);
        if (CollectionUtils.isNotEmpty(dtoList)){
            dtoList = paserDataToExport(dtoList);
        }
        return dtoList;
    }

    /**
     * 解析客户数据由id到汉字
     * 转换地区，客户来源，重要程度，客户状态，所属行业
     *
     * @param dtoList
     * @return
     */
    public List<XnAccountVO> paserDataToExport(List<XnAccountVO> dtoList){
        List<XnAccountVO> voList = new ArrayList<>();
        for (XnAccountVO accountVo : dtoList) {
            XnAccountVO vo = new XnAccountVO();
            BeanUtils.copyProperties(accountVo, vo);
            // 转换地区
            if (StringUtils.isNotBlank(accountVo.getArea())){
                ID areaId = ID.valueOf(accountVo.getArea());
                String itemId = ClassificationManager.instance.getName(areaId);
                vo.setArea(itemId);
            }
            // 客户级别
            if (StringUtils.isNotBlank(accountVo.getRbjibie4())){
                AccountLevelEnum l = AccountLevelEnum.getByKey(accountVo.getRbjibie4());
                vo.setRbjibie4(l.getValue());
            }
            // 客户状态
            if (StringUtils.isNotBlank(accountVo.getKehuzhuangtai())){
                AccountTypeEnum ls =  AccountTypeEnum.getByKey(accountVo.getKehuzhuangtai());
                vo.setKehuzhuangtai(ls.getValue());
            }
            // 所属行业
            if (StringUtils.isNotBlank(accountVo.getIndustry())){
                IndustryEnum in = IndustryEnum.getByValue(accountVo.getIndustry());
                vo.setIndustry(in.getKey());
            }
            voList.add(vo);
        }
        return voList;
    }
}
